Skip to content

fix: New growcut (fill) implementation#5954

Open
wayfarer3130 wants to merge 19 commits into
masterfrom
fix/grow-cut-suv-pt
Open

fix: New growcut (fill) implementation#5954
wayfarer3130 wants to merge 19 commits into
masterfrom
fix/grow-cut-suv-pt

Conversation

@wayfarer3130

@wayfarer3130 wayfarer3130 commented Apr 9, 2026

Copy link
Copy Markdown
Contributor

Context

The old growcut implementation had fundamental issues working with PT type series because of the size/setup of the PT.
This is being replaced by a newer version that uses teh currently displayed image as the base image for determining the cutoff, and uses a flood fill algorithm that is bounded to give reasonable performance for clicking.

Changes & Results

CS3D_REF: fix/grow-cut-suv-pt

Checkout the referenced branch and link/build/run

Mostly changed the growcut version tag to reference the new growcut algorithm.

Testing

If you are using speckled areas (like CT brain matter), check the checkbox to use the full area, otherwise select a bright OR
dark are (high contrast with an edge), and click the circle so there is some inside, some outside regions, and you click on an included point.

Using the full area one click, just click so the circle is entirely within the mottled area.

Checklist

PR

  • [] My Pull Request title is descriptive, accurate and follows the
    semantic-release format and guidelines.

Code

  • [] My code has been well-documented (function documentation, inline comments,
    etc.)

Public Documentation Updates

  • [] The documentation page has been updated as necessary for any public API
    additions or removals.

Tested Environment

  • [] OS:
  • [] Node version:
  • [] Browser:

Summary by CodeRabbit

  • New Features
    • Updated the RegionSegmentPlus segmentation workflow to use a flood-fill based tool.
    • Added “Max Delta K” and “Max Delta IJ” controls to tune flood-fill intensity thresholds.
  • Improvements
    • Refined measurement cancellation to better stop in-flight interactions and rerender after successful cancellation.
  • CI / E2E
    • Improved automated E2E startup by dynamically using the OHIF port and freeing any conflicting listeners before tests.
    • Added portable CS3D setup for CI builds, with Netlify/CircleCI now running the setup prior to building/testing.

Greptile Summary

Replaces the old GrowCut (RegionSegmentPlusTool) implementation with a flood-fill variant (RegionSegmentPlusFloodFillTool) that operates on the currently displayed image slice and is bounded by configurable Max Delta K (slice direction) and Max Delta IJ (in-plane) parameters. The CI Playwright setup gains a cross-platform port-cleanup script (free-ohif-e2e-port.mjs) that runs before the dev server starts, and the config is refactored to drive the port from a single OHIF_PORT env var.

  • initCornerstoneTools.js / initToolGroups.ts — tool registration and initial configuration wired to the new flood-fill tool.
  • commandsModule.ts — adds _getRegionSegmentPlusLimits, cancelMeasurement (also hooked into rejectPreview for ESC cancellation), and setRegionSegmentPlusFloodFillConfiguration which updates both the toolbar sliders and the live tool configuration.
  • playwright.config.ts / free-ohif-e2e-port.mjs — CI improvements: parameterised port, reduced workers (18 → 6), and pre-server port cleanup on self-hosted runners.

Confidence Score: 5/5

Safe to merge; the core flood-fill tool swap is clean and the CI helper is well-guarded.

The tool replacement is mechanical (import swap + configuration block), and the new command logic is well-structured. Issues flagged in earlier review threads (imageData fallback, toolbar option mutation, Windows findstr substring match) are the only open concerns; no new blocking problems were found in this pass.

extensions/cornerstone/src/commandsModule.ts — open items from prior threads around the imageData fallback branch and toolbar option mutation remain unresolved.

Important Files Changed

Filename Overview
extensions/cornerstone/src/commandsModule.ts Adds _getRegionSegmentPlusLimits, cancelMeasurement, and setRegionSegmentPlusFloodFillConfiguration; rejectPreview now calls cancelMeasurement; all notable issues were flagged in prior review threads.
.scripts/ci/free-ohif-e2e-port.mjs New CI helper that finds and kills any process holding the Playwright e2e port; cross-platform (macOS lsof, Linux lsof/ss/fuser, Windows netstat+findstr); Windows findstr substring-match concern flagged in prior thread.
modes/segmentation/src/toolbarButtons.ts Updates RegionSegmentPlus button: new tooltip, evaluate toolNames updated to RegionSegmentPlusFloodFill, two range-slider options (Max Delta K/IJ) added, and setRegionSegmentPlusFloodFillConfiguration wired into commands.
playwright.config.ts Port parameterised via OHIF_PORT env var, workers reduced from 18 to 6, video switched to on-first-retry, --use-gl=egl removed, and port-cleanup command prepended in CI mode.
extensions/cornerstone/src/initCornerstoneTools.js Swaps RegionSegmentPlusTool for RegionSegmentPlusFloodFillTool in registration, addTool, and toolNames map — straightforward tool replacement with no logic changes.
modes/segmentation/src/initToolGroups.ts Adds initial configuration block for RegionSegmentPlus with flood-fill defaults (hoverPrecheckEnabled: false, canvasDiskTriClassLarge strategy, maxDeltaK/IJ); values match command-module defaults so first activation is consistent.

Reviews (7): Last reviewed commit: "Merge remote-tracking branch 'origin/mas..." | Re-trigger Greptile

@wayfarer3130 wayfarer3130 added the ohif-integration Causes a CS3D/OHIF integraiton build to be run label Apr 9, 2026
@netlify

netlify Bot commented Apr 9, 2026

Copy link
Copy Markdown

Deploy Preview for ohif-dev ready!

Name Link
🔨 Latest commit 1932467
🔍 Latest deploy log https://app.netlify.com/projects/ohif-dev/deploys/6a3ecd5a23703400087c4718
😎 Deploy Preview https://deploy-preview-5954--ohif-dev.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

Comment thread extensions/cornerstone/src/commandsModule.ts
Comment thread extensions/cornerstone/src/commandsModule.ts Outdated
Comment thread extensions/cornerstone/src/commandsModule.ts
@cypress

cypress Bot commented Apr 16, 2026

Copy link
Copy Markdown

Viewers    Run #6439

Run Properties:  status check passed Passed #6439  •  git commit 1932467264: fix(ci): sync cached CS3D branch checkout to HEAD on CI
Project Viewers
Branch Review fix/grow-cut-suv-pt
Run status status check passed Passed #6439
Run duration 02m 07s
Commit git commit 1932467264: fix(ci): sync cached CS3D branch checkout to HEAD on CI
Committer Bill Wallace
View all properties for this run ↗︎

Test results
Tests that failed  Failures 0
Tests that were flaky  Flaky 0
Tests that did not run due to a developer annotating a test with .skip  Pending 0
Tests that did not run due to a failure in a mocha hook  Skipped 0
Tests that passed  Passing 28
View all changes introduced in this branch ↗︎

@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds CI helpers for freeing the E2E port and setting up Cornerstone3D refs, updates Playwright to use dynamic port values, and migrates RegionSegmentPlus to a flood-fill tool with adjustable delta limits.

Changes

Port-freeing utility and Playwright integration

Layer / File(s) Summary
Port-freeing utility script implementation
.scripts/ci/free-ohif-e2e-port.mjs
Exports port validation and cross-platform port cleanup, including Unix and Windows listener discovery, process termination, Linux fallback handling, and direct execution.
Playwright dynamic port and CI command
playwright.config.ts
Derives the E2E port and base URL from OHIF_PORT, conditionally prepends the port-freeing script in CI, and wires the dynamic values into Playwright’s base URL and web server config.

CS3D CI setup

Layer / File(s) Summary
CS3D ref selection and setup script
.cs3d-ref, .circleci/config.yml, .scripts/ci/setup-cs3d.sh
Adds a configured Cornerstone3D ref, runs the setup helper in CircleCI, and implements ref resolution plus version-or-branch setup and linking.
Netlify build hook
netlify.toml
Prepends the Netlify build command with the CS3D setup script and documents the ref-based build flow in the build config comments.

RegionSegmentPlus flood-fill migration

Layer / File(s) Summary
Tool registration switch to flood-fill variant
extensions/cornerstone/src/initCornerstoneTools.js
Updates the Cornerstone tool registration and exported tool name mapping to use RegionSegmentPlusFloodFillTool.
Tool group initial configuration
modes/segmentation/src/initToolGroups.ts
Adds a configuration block to the RegionSegmentPlus tool entry with hover precheck disabling, intensity strategy selection, delta limits, and preview disabling.
Configuration commands and toolbar UI
extensions/cornerstone/src/commandsModule.ts, modes/segmentation/src/toolbarButtons.ts
Adds viewport-based delta limit helpers, measurement cancellation, flood-fill configuration commands, and toolbar controls for the new flood-fill parameters.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Suggested reviewers

  • sedghi
  • jbocce

Poem

🐇 I hopped through ports and cleared the way,
Then flood-fill danced in bright array.
A CS3D ref joined the CI run,
Delta knobs twirled in the sun.
Hop, click, build—success is near,
With bunny joy and no stale peer.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise, semantic-release style, and clearly describes the new growcut/fill implementation.
Description check ✅ Passed The description includes the required Context, Changes & Results, Testing, and Checklist sections and is mostly complete.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/grow-cut-suv-pt

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Comment thread .scripts/ci/free-ohif-e2e-port.mjs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
modes/segmentation/src/toolbarButtons.ts (1)

766-822: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Pass the flood-fill tool name explicitly when activating this button.

This button still uses id: 'RegionSegmentPlus', but setToolActiveToolbar resolves the target from toolName || itemId || value (extensions/cornerstone/src/commandsModule.ts, Line 1129). With the updated registration/evaluate path now using RegionSegmentPlusFloodFill, clicking the button can no-op because it still activates the legacy id instead of the registered tool name.

Suggested fix
       commands: [
-        'setToolActiveToolbar',
+        {
+          commandName: 'setToolActiveToolbar',
+          commandOptions: {
+            toolName: 'RegionSegmentPlusFloodFill',
+          },
+        },
         'setRegionSegmentPlusFloodFillConfiguration',
         {
           commandName: 'activateSelectedSegmentationOfType',
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@modes/segmentation/src/toolbarButtons.ts` around lines 766 - 822, The toolbar
button currently uses id 'RegionSegmentPlus' but setToolActiveToolbar resolves
targets from toolName || itemId || value so it may activate the wrong legacy id;
update the commands for this button (the commands array that currently includes
'setToolActiveToolbar') to pass the flood-fill tool name explicitly (e.g.,
include a command entry invoking setToolActiveToolbar with toolName:
'RegionSegmentPlusFloodFill' or set the value to 'RegionSegmentPlusFloodFill')
so activation targets the registered tool; locate the button definition (id:
'RegionSegmentPlus') in modes/segmentation/src/toolbarButtons.ts and modify the
commands element to supply the explicit tool name when calling
setToolActiveToolbar.
🧹 Nitpick comments (1)
playwright.config.ts (1)

3-4: 💤 Low value

Consider validating OHIF_PORT to match the utility script's validation.

The port-freeing utility (free-ohif-e2e-port.mjs) validates that OHIF_PORT is an integer in range 1-65535 and throws a descriptive error if invalid. This config file uses Number(process.env.OHIF_PORT || 3335) without validation, which would produce NaN for non-numeric values like "abc", leading to a confusing http://localhost:NaN URL.

♻️ Suggested validation
-const E2E_PORT = Number(process.env.OHIF_PORT || 3335);
+const E2E_PORT = (() => {
+  const port = Number(process.env.OHIF_PORT || 3335);
+  if (!Number.isInteger(port) || port < 1 || port > 65535) {
+    throw new Error(`Invalid OHIF_PORT: ${process.env.OHIF_PORT}`);
+  }
+  return port;
+})();
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@playwright.config.ts` around lines 3 - 4, E2E_PORT is set using Number(...)
without validation which can produce NaN for bad env values; replicate the
utility script's validation: read process.env.OHIF_PORT, if present parse it as
an integer (base 10), ensure it's an integer between 1 and 65535, and if invalid
throw a descriptive Error stating the invalid OHIF_PORT value and expected
range; if not present, use the default 3335. Then set E2E_PORT and E2E_BASE_URL
using the validated integer. Reference the constants E2E_PORT and E2E_BASE_URL
and mirror the validation behavior from free-ohif-e2e-port.mjs.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@extensions/cornerstone/src/commandsModule.ts`:
- Around line 202-240: The function _getRegionSegmentPlusLimits uses direct
instanceof checks for StackViewport and VolumeViewport but those classes are not
imported and bypass the legacy GenericViewport adapters; replace the instanceof
checks by using the existing helper predicates isStackViewportType(viewport) and
isVolumeViewportType(viewport) (importing them if missing) to detect viewport
types, keep the same logic for computing maxDeltaK/maxDeltaIJ, and ensure
csUtils.getImageSliceDataForVolumeViewport(viewport) is only called when
isVolumeViewportType returns true; update imports to include the predicate
functions rather than StackViewport/VolumeViewport classes.

---

Outside diff comments:
In `@modes/segmentation/src/toolbarButtons.ts`:
- Around line 766-822: The toolbar button currently uses id 'RegionSegmentPlus'
but setToolActiveToolbar resolves targets from toolName || itemId || value so it
may activate the wrong legacy id; update the commands for this button (the
commands array that currently includes 'setToolActiveToolbar') to pass the
flood-fill tool name explicitly (e.g., include a command entry invoking
setToolActiveToolbar with toolName: 'RegionSegmentPlusFloodFill' or set the
value to 'RegionSegmentPlusFloodFill') so activation targets the registered
tool; locate the button definition (id: 'RegionSegmentPlus') in
modes/segmentation/src/toolbarButtons.ts and modify the commands element to
supply the explicit tool name when calling setToolActiveToolbar.

---

Nitpick comments:
In `@playwright.config.ts`:
- Around line 3-4: E2E_PORT is set using Number(...) without validation which
can produce NaN for bad env values; replicate the utility script's validation:
read process.env.OHIF_PORT, if present parse it as an integer (base 10), ensure
it's an integer between 1 and 65535, and if invalid throw a descriptive Error
stating the invalid OHIF_PORT value and expected range; if not present, use the
default 3335. Then set E2E_PORT and E2E_BASE_URL using the validated integer.
Reference the constants E2E_PORT and E2E_BASE_URL and mirror the validation
behavior from free-ohif-e2e-port.mjs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 936c80e0-989f-4e34-b998-c88d30ba5898

📥 Commits

Reviewing files that changed from the base of the PR and between 571c2b4 and 6a4ebe3.

📒 Files selected for processing (7)
  • .github/workflows/playwright.yml
  • .scripts/ci/free-ohif-e2e-port.mjs
  • extensions/cornerstone/src/commandsModule.ts
  • extensions/cornerstone/src/initCornerstoneTools.js
  • modes/segmentation/src/initToolGroups.ts
  • modes/segmentation/src/toolbarButtons.ts
  • playwright.config.ts

Comment thread extensions/cornerstone/src/commandsModule.ts
…anch

Squash of origin/feat/ohifpnpm2 (#6031) which converts the
monorepo build to pnpm + Rspack, node >=24, and adds the cs3d:* dev
helper scripts. Brought in onto fix/grow-cut-suv-pt ahead of the same
squash landing on origin/master.

Conflict in playwright.config.ts resolved by keeping the grow-cut
branch's CI port-cleanup wrapper (free-ohif-e2e-port.mjs) and parametrized
E2E_PORT/E2E_BASE_URL, while switching the underlying webServer command to
the pnpm/rspack invocation from the pnpm branch.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
.github/workflows/playwright.yml (1)

113-114: ⚠️ Potential issue | 🟠 Major

Fix Windows port cleanup to avoid substring-matching other ports.

Free OHIF e2e port (stale self-hosted processes) runs .scripts/ci/free-ohif-e2e-port.mjs before Playwright tests. On win32, the script uses netstat -ano | findstr :${port} | findstr LISTENING, which matches substrings (e.g., :3335 can also match :33350) and can kill unrelated listener processes on the runner.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/playwright.yml around lines 113 - 114, The Windows
port-cleanup is using netstat + findstr with a substring match (in
.scripts/ci/free-ohif-e2e-port.mjs), which can match ports like 33350 when you
meant 3335; update the win32 branch to match the exact port: either replace the
netstat|findstr pipeline with a PowerShell query (Get-NetTCPConnection
-LocalPort <port> | Where-Object State -eq 'Listen' to get exact listeners and
their PIDs) or change the findstr invocation to a strict regex (e.g., findstr /R
/C:":<port>\\b" or include the trailing space/column delimiter) so only the
exact port is matched before killing processes (adjust logic in the function
that builds the command in free-ohif-e2e-port.mjs).
platform/app/package.json (1)

4-4: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Duplicate productVersion key in JSON.

productVersion appears at both line 4 and line 103. JSON parsers will use the last occurrence, but this duplication is likely unintentional and confusing. Remove the duplicate at line 103.

   "tailwindcss": "3.2.4"
   },
-  "productVersion": "3.4.0",
   "proxy": "http://localhost:8042"
 }

Also applies to: 103-103

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@platform/app/package.json` at line 4, Remove the duplicate JSON key by
deleting the later occurrence of "productVersion" so only a single
"productVersion": "3.4.0" remains; locate the duplicate key named
"productVersion" (the second occurrence near the end of the file) and remove
that entry, then validate the package.json syntax (e.g., with JSON lint or npm
pack) to ensure no trailing commas or structural errors remain.
🧹 Nitpick comments (4)
platform/docs/docs/platform/modes/index.md (1)

454-459: ⚡ Quick win

Clarify "generating modes with an agent".

The note mentions the CLI "is being phased out in favour of generating modes with an agent" but doesn't specify which agent or link to documentation. Users reading this may not understand what "agent" means in this context (AI agent? build agent? custom tooling?). Consider adding a link or brief explanation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@platform/docs/docs/platform/modes/index.md` around lines 454 - 459, The note
in the "modes" documentation uses the ambiguous phrase "generating modes with an
agent" without specifying which agent or linking to relevant docs; update the
note in the index.md "modes" section to clarify what "agent" means (e.g.,
specify "AI agent", "automation agent", or the specific tool name) and add a
short parenthetical explanation plus a link to the appropriate documentation or
README for the agent (or to the development/agents page) so readers know which
agent to use and where to find usage/installation instructions; keep the
existing mention of the CLI but indicate it is being phased out in favor of the
named agent.
tests/SegmentationPanel.spec.ts (1)

23-29: ⚡ Quick win

Keep segment-count assertions on the page-object API.

Please switch these back to await panel.getSegmentCount() plus expect(count).toBe(...) rather than asserting on panel.rows directly. This project already standardized on the page-object count helper for segmentation tests, so bypassing it here makes the suite less consistent and harder to evolve if the underlying locator changes.

Based on learnings: "In OHIF/Viewers Playwright tests, prefer asserting segment counts via the relevant page object’s getSegmentCount() method ... Do not suggest replacing these getSegmentCount() + expect(...).toBe(...) assertions with Playwright locator-based expect(locator).toHaveCount(n) for this project."

Also applies to: 40-41

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/SegmentationPanel.spec.ts` around lines 23 - 29, Replace direct locator
count assertions on panel.rows with the page-object API: call
panel.getSegmentCount() and assert using expect(count).toBe(expected).
Specifically, change the two places where the test uses await
expect(panel.rows).toHaveCount(1) (and the similar assertion at lines 40-41) to
use const count = await panel.getSegmentCount(); await expect(count).toBe(1) (or
expect(count).toBe(...)), while keeping the segment text check via
panel.nthSegment(0).locator; this preserves the standardized page-object
abstraction (panel.getSegmentCount, panel.nthSegment).

Source: Learnings

extensions/measurement-tracking/package.json (2)

42-42: 💤 Low value

webpack-merge is declared in both peerDependencies and devDependencies.

This duplication is redundant. If it's needed for build configuration, keeping it only in devDependencies is sufficient for development, and it doesn't need to be a peer dependency unless external consumers must provide it.

   "peerDependencies": {
     ...
     "react-dom": "18.3.1",
-    "webpack-merge": "5.10.0"
   },

Also applies to: 50-52

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@extensions/measurement-tracking/package.json` at line 42, The package.json
declares "webpack-merge" in both peerDependencies and devDependencies which is
redundant; remove the duplicate entry from peerDependencies and keep
"webpack-merge" only in devDependencies (or vice-versa if you intentionally
require consumers to provide it) and update the peerDependencies block
accordingly; also check and remove the duplicate occurrences referenced around
the other reported lines (50-52) so "webpack-merge" appears only once in the
manifest.

35-35: 💤 Low value

@ohif/ui is declared in both peerDependencies and dependencies.

Having the same package in both sections creates ambiguity about resolution. Typically, if it's a peer dependency, it should not also be in direct dependencies. Consider removing it from one section (likely dependencies if the consuming app is expected to provide it).

   "dependencies": {
     "`@babel/runtime`": "7.29.7",
-    "`@ohif/ui`": "workspace:*",
     "`@xstate/react`": "3.2.2",
     "xstate": "4.38.3"
   },

Also applies to: 44-49

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@extensions/measurement-tracking/package.json` at line 35, The package.json
currently lists "`@ohif/ui`" in both dependencies and peerDependencies which
causes ambiguity; remove the duplicate by keeping it only in peerDependencies
(so the host app provides it) and delete the "`@ohif/ui`" entry from dependencies
(also remove any duplicate entries around lines 44-49 mentioned in the review)
to ensure a single source of truth for resolution.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/build-docs.yml:
- Line 81: The gh run download step uses the unvalidated expression `${{
steps.find_pr_run.outputs.run_id }}` which could be abused if its format
changes; fix by validating that `steps.find_pr_run.outputs.run_id` contains only
digits before invoking `gh run download` (e.g., add a prior step that checks
`/^\d+$/` and fails if not) and then use the validated value (or a sanitized
output variable) in the `gh run download` command (also wrap the injected value
in quotes or pass it via a safe flag) so the `run_id` is guaranteed numeric and
cannot be used for command injection.

In `@extensions/cornerstone-dicom-sr/package.json`:
- Around line 23-25: The dev script in modes/segmentation's package.json calls
rspack with .webpack/webpack.dev.js but that file is missing; add a
.webpack/webpack.dev.js for modes/segmentation (or change the dev script) so the
dev build works. Fix by creating modes/segmentation/.webpack/webpack.dev.js that
mirrors the pattern used in extensions/cornerstone-dicom-sr and
modes/usAnnotation: require or import the shared .webpack/webpack.base.js, set
mode to "development" and export the config (ensuring compatibility with
`@rspack/core`), or alternatively change the dev script to point to the existing
.webpack/webpack.prod.js if that is intentional.

In `@modes/tmtv/package.json`:
- Around line 31-38: The peerDependencies block in modes/tmtv/package.json (and
likewise in extensions/cornerstone/package.json) currently uses monorepo-only
"workspace:*" ranges for entries like "`@ohif/core`",
"`@ohif/extension-cornerstone`", "`@ohif/extension-default`", etc.; replace every
"workspace:*" with an appropriate semver range (e.g. ^<version> or a range
matching the published package versions) so the published package exposes real
semver peer ranges; ensure you update each dependency key in the
"peerDependencies" object to the chosen semver (matching the root/monorepo
published versions) and run npm pack / npm publish dry-run to verify no
workspace protocol remains.

In `@platform/cli/src/commands/utils/getYarnInfo.js`:
- Around line 4-5: getYarnInfo currently returns JSON.parse(stdout) directly
from execa('npm', ['info', packageName, '--json']) which can be either an object
or an array; normalize the parsed result to preserve the previous return shape
by detecting if the parsed value is an array and selecting the appropriate
element (e.g., first item or the one matching packageName) or converting an
array into a single object with expected fields (peerDependencies, version,
etc.), and ensure getYarnInfo always returns an object with those fields; update
getYarnInfo to handle null/undefined stdout and throw or return a consistent
empty shape, and add a small unit test that simulates npm info returning both an
object and an array for the same package spec to assert the normalized shape is
returned.

In `@platform/core/package.json`:
- Line 21: The package.json currently sets "sideEffects" as a string ("false")
which can be misinterpreted by bundlers; change the value to the boolean false
(i.e., sideEffects: false) in the package.json so bundlers correctly treat the
package as side-effect-free and enable proper tree-shaking, ensuring the JSON
remains valid.

In `@platform/docs/docs/migration-guide/3p12-to-3p13/node-version.md`:
- Line 59: Update the CI reference line to use the proper product name and
capitalization: replace the lowercase "GitHub" occurrence in the phrase "CI
config (`.github/workflows/*`, `.circleci/config.yml`, " with the correctly
capitalized product name "GitHub Actions" so the line reads something like "CI
config (GitHub Actions `.github/workflows/*`, `.circleci/config.yml`, ..."
ensuring consistent capitalization and explicit mention of "GitHub Actions".
- Line 25: The doc string in node-version.md lists the pnpm engine as "pnpm":
"11.1.1" but templates now declare "pnpm": ">=11" in dependencies.json; update
node-version.md to match the generated manifest (change the documented pnpm
requirement to ">=11" or otherwise mirror the exact engine string used in
platform/cli/templates/mode/dependencies.json) and check the other occurrences
noted (lines 56–58) for the same mismatch so the documentation and template stay
consistent.

In `@platform/docs/docs/migration-guide/3p12-to-3p13/package-manager.md`:
- Around line 156-162: The package.json script examples contain malformed pnpm
invocations: update the script values for "dev:my-extension" and "start" from
"pnpm rundev" to "pnpm run dev", and update "build:package" from "pnpm runbuild"
to "pnpm run build" so the "pnpm run <script>" form is used correctly (look for
the "dev:my-extension", "build:package", and "start" entries to locate and fix
the strings).

In `@platform/ui-next/package.json`:
- Around line 9-17: The package.json currently exposes subpath exports (e.g.,
"./tailwind.config", "./lib/*", "./components/*", ".") that point at source
files (tailwind.config.js and src/**) but the "files" array only includes "dist"
and "README.md", causing published consumers to miss those exported paths; fix
by updating the "exports" entries to reference built outputs under dist (for
example change "./tailwind.config" and the "./lib/*" and "./components/*"
mappings to point at the corresponding files in dist) or alternatively add
"tailwind.config.js" and the relevant "src" paths to the "files" array so those
exported subpaths are included in the package. Ensure changes touch the
package.json keys "exports" and/or "files" so exports and published content
align.

In `@platform/ui/package.json`:
- Line 13: Update the repo documentation to state Node 24 is the new supported
baseline: make sure the package.json engines.node entry (engines.node) and
.node-version align with Node 24, then add a clear note in the README and
release notes/changelog indicating "Node >=24 (Node 24 LTS)" as the minimum
supported version, call out breaking compatibility with Node 18/20/22, and add a
short migration snippet (recommended upgrade steps and an nvm/snippet
suggestion) so consumers know how to upgrade; also mention where CI/Docker were
updated (CI node-version and Docker FROM node:24-slim) so readers understand the
change is repo-wide.

In `@publish-version.mjs`:
- Around line 88-95: The push of the tag (the execa call that currently runs
execa('git', ['push', 'origin', tagName'])) can fail if the remote already has
that tag because you only force the local tag (git tag -f) but not the remote
push; update the tag push to either include --force (execa('git', ['push',
'--force', 'origin', tagName'])) to match the local behavior or wrap the
existing execa call in a try/catch and on failure delete the remote tag (git
push origin :refs/tags/<tagName> or git tag -d <tagName> remote deletion) then
retry pushing tagName; locate the occurrences of tagName and branchName and the
execa('git', ...) calls to implement the change.

In `@tests/pages/RightPanelPageObject.ts`:
- Around line 227-231: The `rows` locator and getSegmentCount use a global
page.getByTestId('data-row'), causing flaky counts; scope them to the
segmentation panel root instead. Define a segmentation-panel-scoped locator
(e.g., segmentationRoot = page.getByTestId('segmentation-panel') or the existing
segmentation panel locator) and replace occurrences so rows =
segmentationRoot.getByTestId('data-row'); update getSegmentCount and any helpers
that reference rows/index/text to reuse that scoped rows locator.

---

Outside diff comments:
In @.github/workflows/playwright.yml:
- Around line 113-114: The Windows port-cleanup is using netstat + findstr with
a substring match (in .scripts/ci/free-ohif-e2e-port.mjs), which can match ports
like 33350 when you meant 3335; update the win32 branch to match the exact port:
either replace the netstat|findstr pipeline with a PowerShell query
(Get-NetTCPConnection -LocalPort <port> | Where-Object State -eq 'Listen' to get
exact listeners and their PIDs) or change the findstr invocation to a strict
regex (e.g., findstr /R /C:":<port>\\b" or include the trailing space/column
delimiter) so only the exact port is matched before killing processes (adjust
logic in the function that builds the command in free-ohif-e2e-port.mjs).

In `@platform/app/package.json`:
- Line 4: Remove the duplicate JSON key by deleting the later occurrence of
"productVersion" so only a single "productVersion": "3.4.0" remains; locate the
duplicate key named "productVersion" (the second occurrence near the end of the
file) and remove that entry, then validate the package.json syntax (e.g., with
JSON lint or npm pack) to ensure no trailing commas or structural errors remain.

---

Nitpick comments:
In `@extensions/measurement-tracking/package.json`:
- Line 42: The package.json declares "webpack-merge" in both peerDependencies
and devDependencies which is redundant; remove the duplicate entry from
peerDependencies and keep "webpack-merge" only in devDependencies (or vice-versa
if you intentionally require consumers to provide it) and update the
peerDependencies block accordingly; also check and remove the duplicate
occurrences referenced around the other reported lines (50-52) so
"webpack-merge" appears only once in the manifest.
- Line 35: The package.json currently lists "`@ohif/ui`" in both dependencies and
peerDependencies which causes ambiguity; remove the duplicate by keeping it only
in peerDependencies (so the host app provides it) and delete the "`@ohif/ui`"
entry from dependencies (also remove any duplicate entries around lines 44-49
mentioned in the review) to ensure a single source of truth for resolution.

In `@platform/docs/docs/platform/modes/index.md`:
- Around line 454-459: The note in the "modes" documentation uses the ambiguous
phrase "generating modes with an agent" without specifying which agent or
linking to relevant docs; update the note in the index.md "modes" section to
clarify what "agent" means (e.g., specify "AI agent", "automation agent", or the
specific tool name) and add a short parenthetical explanation plus a link to the
appropriate documentation or README for the agent (or to the development/agents
page) so readers know which agent to use and where to find usage/installation
instructions; keep the existing mention of the CLI but indicate it is being
phased out in favor of the named agent.

In `@tests/SegmentationPanel.spec.ts`:
- Around line 23-29: Replace direct locator count assertions on panel.rows with
the page-object API: call panel.getSegmentCount() and assert using
expect(count).toBe(expected). Specifically, change the two places where the test
uses await expect(panel.rows).toHaveCount(1) (and the similar assertion at lines
40-41) to use const count = await panel.getSegmentCount(); await
expect(count).toBe(1) (or expect(count).toBe(...)), while keeping the segment
text check via panel.nthSegment(0).locator; this preserves the standardized
page-object abstraction (panel.getSegmentCount, panel.nthSegment).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 24d573f6-1c2d-43d0-aa22-d8df0d4590c6

📥 Commits

Reviewing files that changed from the base of the PR and between 6a4ebe3 and 5f49a51.

⛔ Files ignored due to path filters (42)
  • .webpack/resolveConfig.js is excluded by !**/.webpack/**
  • .webpack/rules/cssToJavaScript.js is excluded by !**/.webpack/**
  • .webpack/rules/transpileJavaScript.js is excluded by !**/.webpack/**
  • .webpack/webpack.base.js is excluded by !**/.webpack/**
  • bun.lock is excluded by !**/*.lock
  • extensions/cornerstone-dicom-pmap/.webpack/webpack.prod.js is excluded by !**/.webpack/**
  • extensions/cornerstone-dicom-rt/.webpack/webpack.prod.js is excluded by !**/.webpack/**
  • extensions/cornerstone-dicom-seg/.webpack/webpack.prod.js is excluded by !**/.webpack/**
  • extensions/cornerstone-dicom-sr/.webpack/webpack.prod.js is excluded by !**/.webpack/**
  • extensions/cornerstone-dynamic-volume/.webpack/webpack.prod.js is excluded by !**/.webpack/**
  • extensions/cornerstone/.webpack/webpack.prod.js is excluded by !**/.webpack/**
  • extensions/default/.webpack/webpack.prod.js is excluded by !**/.webpack/**
  • extensions/dicom-microscopy/.webpack/webpack.prod.js is excluded by !**/.webpack/**
  • extensions/dicom-pdf/.webpack/webpack.prod.js is excluded by !**/.webpack/**
  • extensions/dicom-video/.webpack/webpack.prod.js is excluded by !**/.webpack/**
  • extensions/measurement-tracking/.webpack/webpack.prod.js is excluded by !**/.webpack/**
  • extensions/test-extension/.webpack/webpack.prod.js is excluded by !**/.webpack/**
  • extensions/tmtv/.webpack/webpack.prod.js is excluded by !**/.webpack/**
  • extensions/usAnnotation/.webpack/webpack.prod.js is excluded by !**/.webpack/**
  • modes/basic-dev-mode/.webpack/webpack.prod.js is excluded by !**/.webpack/**
  • modes/basic-test-mode/.webpack/webpack.prod.js is excluded by !**/.webpack/**
  • modes/basic/.webpack/webpack.prod.js is excluded by !**/.webpack/**
  • modes/longitudinal/.webpack/webpack.prod.js is excluded by !**/.webpack/**
  • modes/microscopy/.webpack/webpack.prod.js is excluded by !**/.webpack/**
  • modes/preclinical-4d/.webpack/webpack.prod.js is excluded by !**/.webpack/**
  • modes/segmentation/.webpack/webpack.prod.js is excluded by !**/.webpack/**
  • modes/tmtv/.webpack/webpack.prod.js is excluded by !**/.webpack/**
  • modes/usAnnotation/.webpack/webpack.prod.js is excluded by !**/.webpack/**
  • platform/app/.webpack/rules/extractStyleChunks.js is excluded by !**/.webpack/**
  • platform/app/.webpack/webpack.pwa.js is excluded by !**/.webpack/**
  • platform/app/.webpack/writePluginImportsFile.js is excluded by !**/.webpack/**
  • platform/cli/templates/extension/.webpack/webpack.prod.js is excluded by !**/.webpack/**
  • platform/cli/templates/mode/.webpack/webpack.prod.js is excluded by !**/.webpack/**
  • platform/core/.webpack/webpack.prod.js is excluded by !**/.webpack/**
  • platform/docs/bun.lockb is excluded by !**/bun.lockb
  • platform/docs/yarn.lock is excluded by !**/yarn.lock, !**/*.lock
  • platform/i18n/.webpack/webpack.prod.js is excluded by !**/.webpack/**
  • platform/ui-next/.webpack/webpack.prod.js is excluded by !**/.webpack/**
  • platform/ui/.webpack/webpack.prod.js is excluded by !**/.webpack/**
  • platform/ui/a34f9d1faa5f3315.woff2 is excluded by !**/*.woff2
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (84)
  • .circleci/config.yml
  • .github/.dependabot.yaml
  • .github/workflows/build-docs.yml
  • .github/workflows/codeql.yml
  • .github/workflows/playwright.yml
  • .gitignore
  • .netlify/build-deploy-preview.sh
  • .netlify/package.json
  • .node-version
  • .npmrc
  • .scripts/dev.sh
  • Dockerfile
  • addOns/README.md
  • addOns/externals/devDependencies/CHANGELOG.md
  • addOns/externals/devDependencies/package.json
  • addOns/externals/dicom-microscopy-viewer/CHANGELOG.md
  • addOns/externals/dicom-microscopy-viewer/package.json
  • addOns/package.json
  • bunfig.toml
  • bunfig.update-lockfile.toml
  • extensions/cornerstone-dicom-pmap/package.json
  • extensions/cornerstone-dicom-rt/package.json
  • extensions/cornerstone-dicom-seg/package.json
  • extensions/cornerstone-dicom-sr/package.json
  • extensions/cornerstone-dynamic-volume/package.json
  • extensions/cornerstone/package.json
  • extensions/default/package.json
  • extensions/default/src/ViewerLayout/index.tsx
  • extensions/dicom-microscopy/package.json
  • extensions/dicom-pdf/package.json
  • extensions/dicom-video/package.json
  • extensions/measurement-tracking/package.json
  • extensions/test-extension/package.json
  • extensions/tmtv/package.json
  • extensions/usAnnotation/package.json
  • lerna.json
  • modes/basic-dev-mode/package.json
  • modes/basic-test-mode/package.json
  • modes/basic/package.json
  • modes/longitudinal/package.json
  • modes/microscopy/package.json
  • modes/preclinical-4d/package.json
  • modes/segmentation/package.json
  • modes/tmtv/package.json
  • modes/usAnnotation/package.json
  • netlify-lerna-cache.sh
  • netlify-lerna-restore.sh
  • netlify.toml
  • nx.json
  • package.json
  • platform/app/cypress.config.ts
  • platform/app/cypress/integration/measurement-tracking/OHIFSaveMeasurements.spec.js
  • platform/app/cypress/support/commands.js
  • platform/app/package.json
  • platform/app/tailwind.config.js
  • platform/cli/package.json
  • platform/cli/src/commands/createPackage.js
  • platform/cli/src/commands/utils/getYarnInfo.js
  • platform/cli/src/commands/utils/uninstallNPMPackage.js
  • platform/cli/src/index.js
  • platform/cli/templates/extension/dependencies.json
  • platform/cli/templates/mode/dependencies.json
  • platform/core/package.json
  • platform/docs/docs/migration-guide/3p12-to-3p13/build-tooling.md
  • platform/docs/docs/migration-guide/3p12-to-3p13/index.md
  • platform/docs/docs/migration-guide/3p12-to-3p13/node-version.md
  • platform/docs/docs/migration-guide/3p12-to-3p13/package-manager.md
  • platform/docs/docs/platform/extensions/index.md
  • platform/docs/docs/platform/extensions/pluginConfig.md
  • platform/docs/docs/platform/modes/index.md
  • platform/docs/package.json
  • platform/i18n/package.json
  • platform/ui-next/package.json
  • platform/ui/package.json
  • playwright.config.ts
  • pnpm-workspace.yaml
  • publish-package.mjs
  • publish-version.mjs
  • rsbuild.config.ts
  • tests/FreehandROI.spec.ts
  • tests/SegmentationPanel.spec.ts
  • tests/globalSetup.ts
  • tests/pages/RightPanelPageObject.ts
  • version.mjs
💤 Files with no reviewable changes (11)
  • addOns/package.json
  • nx.json
  • netlify-lerna-cache.sh
  • addOns/externals/dicom-microscopy-viewer/package.json
  • addOns/README.md
  • platform/app/cypress/integration/measurement-tracking/OHIFSaveMeasurements.spec.js
  • lerna.json
  • bunfig.toml
  • netlify-lerna-restore.sh
  • addOns/externals/devDependencies/package.json
  • bunfig.update-lockfile.toml
✅ Files skipped from review due to trivial changes (6)
  • .netlify/package.json
  • .npmrc
  • platform/docs/docs/migration-guide/3p12-to-3p13/index.md
  • platform/docs/docs/platform/extensions/index.md
  • platform/docs/docs/platform/extensions/pluginConfig.md
  • platform/docs/docs/migration-guide/3p12-to-3p13/build-tooling.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • playwright.config.ts

Comment thread .github/workflows/build-docs.yml
Comment thread extensions/cornerstone-dicom-sr/package.json
Comment thread modes/tmtv/package.json
Comment thread platform/cli/src/commands/utils/getYarnInfo.js
Comment thread platform/core/package.json
Comment thread platform/docs/docs/migration-guide/3p12-to-3p13/package-manager.md
Comment thread platform/ui-next/package.json
Comment thread platform/ui/package.json
Comment thread publish-version.mjs
Comment thread tests/pages/RightPanelPageObject.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.circleci/config.yml:
- Around line 434-441: The CS3D integration setup step in the CircleCI config is
currently enabled for every CYPRESS job and can be redirected by a committed
.cs3d-ref. Add explicit branch-based gating like the Playwright workflow around
the setup-cs3d.sh invocation, or make the job fail fast on protected branches
when .cs3d-ref exists, so master CI cannot consume a repo-pinned ref
accidentally.

In @.scripts/ci/setup-cs3d.sh:
- Around line 67-74: The reuse path in setup-cs3d.sh is too permissive: when
libs/@cornerstonejs already exists, it skips cloning without verifying that the
checkout matches the requested $REPO and $BRANCH. Update the existing-checkout
branch in the checkout logic to inspect the current repository’s origin and
resolved ref before building in place, using the same symbols around the git
clone condition, and hard-fail with a clear cleanup message if the local
checkout does not match the requested revision.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: e6575bfd-ba50-46eb-8b4a-0d2bc93c25d8

📥 Commits

Reviewing files that changed from the base of the PR and between 2dd6e11 and e7268eb.

📒 Files selected for processing (3)
  • .circleci/config.yml
  • .cs3d-ref
  • .scripts/ci/setup-cs3d.sh

Comment thread .circleci/config.yml
Comment thread .scripts/ci/setup-cs3d.sh Outdated
@wayfarer3130

Copy link
Copy Markdown
Contributor Author

@james-hanks - could you test this PR a bit with:
https://deploy-preview-5954--ohif-dev.netlify.app/segmentation?StudyInstanceUIDs=1.3.6.1.4.1.14519.5.2.1.7009.2403.334240657131972136850343327463
or some of the other PR's? It seems reasonable to me - I've been testing on the PET AC around frame 16 on the white area, so that it goes against the intended use.
It also seems quite stable against the CT image, although you need a refresh/separate segmentation to get it to work against the CT since the underlying data is different for running the one click on PET versus CT.

@dan-rukas - can you check the one click segmentation sliders - this is the Max Delta K and Max Delta IJ sliders. They are in the standard spot, but they differ from th eprevious behaviour, so you should take a look.

wayfarer3130 and others added 3 commits June 26, 2026 12:03
Pull in latest @cornerstonejs/* (fix/grow-cut-suv-pt): inverted-LUT flood
fill band fix and RegionSegmentPlus circle cursor.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Re-trigger Netlify deploy preview after a transient infra-level failure
(build passes locally and on CircleCI for the prior commit).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Netlify/CircleCI restore the gitignored libs/@cornerstonejs from build
cache, so setup-cs3d.sh saw it "already present" and skipped the clone —
silently building a stale CS3D commit with broken workspace links (tools
resolving the published @cornerstonejs/core, dual @kitware/vtk.js), which
failed the deploy-preview build.

On CI (detected via $CI), hard-reset the cached checkout to the branch
HEAD and clean ignored build/install artifacts so the reinstall relinks
the workspace cleanly. Local builds are unchanged: the destructive path
requires $CI (or explicit CS3D_SYNC=1) and is additionally refused for a
linked git worktree, so uncommitted local work is never wiped.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@wayfarer3130

Copy link
Copy Markdown
Contributor Author

@sedghi - only the OHIF merge guard is still failing. That will be fixed by releasing the CS3D side and update the dependencies, while clearing the .cs3d_ref value

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ohif-integration Causes a CS3D/OHIF integraiton build to be run

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant